using System;
using System.Reflection;
using System.IO;
using System.Collections;

namespace NCover.Utilities
{

	[AttributeUsage(AttributeTargets.Field)]
	public sealed class ArgumentDescriptionAttribute : Attribute
	{
		string _desc;

		public ArgumentDescriptionAttribute(string desc)
		{
			Descripiton = desc;
		}

		public string Descripiton
		{
			get { NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(152); NCover.NCoverCheck.Add(152); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); return _desc; }
			set 
			{
				_desc = value;
			}
		}

		/// <summary>
		/// Check argument is in correct format and parses it.
		/// </summary>
		private static void ParseArgument(string arg, out string key, out string value)
		{
			string [] bits = arg.Split(':');

			if (arg[0] != '/' || bits.Length > 2 && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(166) && NCover.NCoverCheck.Add(166) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167))
			{
				NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(153); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); throw new ArgumentException("arguments should be in form /key:\"value\"", arg);
			}
			
			key = bits[0].Substring(1);

			if (bits.Length == 1 && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(167) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168))
			{
				value = null;
				return;
			}

			if (bits[1][0] == '"' && bits[1][bits[1].Length - 1] == '"' && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(168) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169))
			{
				value = bits[1].Substring(1, bits[1].Length - 2);
			}
			else
			{
				value = bits[1];
			}
		}
	}

	/// <summary>
	/// Responsibilities:
	/// 
	/// Parsing command line arguments.
	/// Throwing exceptions if it wasn't expecting those arguments.
	/// Displaying correct useage information.
	/// </summary>
	public sealed class Arguments
	{
		Hashtable _parametersToValues = new Hashtable();
		CommandLineArgument _validArguments;

		public void WriteUseage( TextWriter writer )
		{
			writer.WriteLine("Useage: /argument:value ");
			writer.WriteLine();

			NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(154); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); foreach ( FieldInfo fieldInfo in typeof(CommandLineArgument).GetFields() )
			{
				if (fieldInfo.IsSpecialName && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(169) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170))
				{
					continue;
				}

				CommandLineArgument arg = (CommandLineArgument) Enum.Parse(typeof(CommandLineArgument), fieldInfo.Name, false);

				if (!ArgumentIsValid(arg) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(170) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171))
				{
					continue;
				}

				ArgumentDescriptionAttribute[] descriptions = (ArgumentDescriptionAttribute[]) fieldInfo.GetCustomAttributes( typeof(ArgumentDescriptionAttribute), false );
				if ( descriptions.Length != 1  && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(171) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172))
				{
					NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(155); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); throw new ApplicationException( "CommandLineArguments should be marked up with one description per argument." );
				}
				writer.WriteLine( "/{0}\t{1}", fieldInfo.Name.Replace('_','-').ToLower(), descriptions[0].Descripiton );
			}
		}

		public CommandLineArgument ValidArguments
		{
			get 
			{ 
				NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(156); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); return _validArguments; 
			}
			set 
			{
				_validArguments = value;
			}
		}

		public bool ArgumentIsValid(CommandLineArgument argName)
		{
			CommandLineArgument x = argName & ValidArguments;
			NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(157); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); return (x) > 0;
		}

		public void Parse(string[] args) 
		{
			CommandLineArgument key;
			string value;
		
			NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(158); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); foreach (string arg in args)
			{
				ParseArgument(arg, out key, out value);
				if (!ArgumentIsValid(key) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(172) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173))
				{
					NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(159); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); throw new ArgumentOutOfRangeException(key.ToString(), value, "Unknown parameter.");
				}
				_parametersToValues[key] = value;
			}
		}

		/// <summary>
		/// Returns default if not specified in command line.
		/// </summary>
		public string this[CommandLineArgument argName, string defaultValue]
		{
			get 
			{
				string result = this[argName];
				NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(160); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); return (result == null)? defaultValue : result;
			}
		}

		/// <summary>
		/// if argName is not valid then throw exeption.
		/// </summary>
		public string this[CommandLineArgument argName] 
		{
			get 
			{
				if (!ArgumentIsValid(argName) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(173) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174))
				{
					NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(161); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); throw new ArgumentException("Command " + argName + " is not registered for use by this task.");
				}

				NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(162); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); return (string)_parametersToValues[argName];
			}
		}


		/// <summary>
		/// Each command line arg should have the form /key:value.
		/// </summary>
		private static Hashtable ParseCommandLine(string[] args)
		{
			Hashtable parameterMap = new Hashtable();
			CommandLineArgument key;
			string value;

			NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(163); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); foreach (string arg in args)
			{
				ParseArgument(arg, out key, out value);
				parameterMap[key] = value;
			}

			NCover.NCoverCheck.Add(167); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(164); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); return parameterMap;
		}

		/// <summary>
		/// Check argument is in correct format and parses it.
		/// </summary>
		public static void ParseArgument(string arg, out CommandLineArgument key, out string value)
		{
			string [] bits = arg.Split(':');

			if (arg[0] != '/' || bits.Length > 2 && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175))
			{
				NCover.NCoverCheck.Add(168); NCover.NCoverCheck.Add(167); NCover.NCoverCheck.Add(167); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(165); NCover.NCoverCheck.Add(167); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); NCover.NCoverCheck.Add(166); throw new ArgumentException("arguments should be in form /key:\"value\"", arg);
			}
			
			key = (CommandLineArgument) Enum.Parse(typeof(CommandLineArgument), bits[0].Substring(1).Replace('-', '_'), true);

			if (bits.Length == 1 && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(174) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176))
			{
				value = String.Empty;
				return;
			}

			if (bits[1][0] == '"' && bits[1][bits[1].Length - 1] == '"' && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(178) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(176) && NCover.NCoverCheck.Add(175) && NCover.NCoverCheck.Add(178) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177) && NCover.NCoverCheck.Add(177))
			{
				value = bits[1].Substring(1, bits[1].Length - 2);
			}
			else
			{
				value = bits[1];
			}
		}
	}
}














